package cn.yitun.chat.yitunserverrunsingleboot.chat.common.service.impl;

import cn.yitun.chat.yituncommonmessage.ExceptionEnum;
import cn.yitun.chat.yituncommonmessage.YitunException;
import cn.yitun.chat.yitunservercommonlib.constant.RedisConstant;
import cn.yitun.chat.yitunservercommonlib.dataentity.dto.system.user.UserDto;
import cn.yitun.chat.yitunserverimcore.general.main.biz.userchat.manager.UserManager;
import cn.yitun.chat.yitunservermanagecore.general.bridge.auth.manager.AuthManager;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * date 2018-06-13 10:41:23<br>
 * description
 * 
 * @author yitun<br>
 * @since
 */
@Service
public class AuthManagerImpl implements AuthManager{

	Map<String, Long> timeMap = new java.util.concurrent.ConcurrentHashMap<>();
	Map<String, Long> tokenMap = new java.util.concurrent.ConcurrentHashMap<>();
	//记录当前用户的token 匹配
//	Map<Long, String> userMap = new java.util.concurrent.ConcurrentHashMap<>();
	// 超级管理员，免认证
	Map<String, Long> authMap = new java.util.concurrent.ConcurrentHashMap<>();
	//xx:xx:xx 形式权限
	Map<String, List<String>> permsMap = new java.util.concurrent.ConcurrentHashMap<>();

	@Resource
	private UserManager userManager;

	/**
	 * 通过遍历map entry 匹配userId 获取token
     * 可能有多个
	 * @param userId
	 * @return
	 */
	@Override
	public List<String> getToken(Long userId) {
	    List<String> tokenList = new ArrayList<>();
	    tokenMap.entrySet().stream().forEach( entry -> {
            if ( userId == entry.getValue()) {
                tokenList.add(entry.getKey());
            }
        });
		return tokenList;
	}
	//新建token
	@Override
	public String createToken(UserDto user) {

		//设置过期时间是当前时间 + 默认过期时间间隔 /s
		return userManager.createJwtToken(user);

	}

	/**
	 * 放置token
	 * @param userId
	 * @param token
	 */
	@Override
	public void putToken(String token, Long userId) {
		tokenMap.put(token, userId);
//		authMap.put(token, userId);
		timeMap.put(token, System.currentTimeMillis());
	}

	/**
	 * token是否有效
	 * @param token
	 * @return
	 */
	@Override
	public boolean isAuth(String token) {
		token = null == token ? "" : token;
		boolean auth = tokenMap.containsKey(token);
		if (auth) {
			//处理过期令牌
			if (System.currentTimeMillis() - timeMap.get(token) > RedisConstant.defalutExpireTime * 1000  ) {
				removeByToken(token);
				throw new YitunException(ExceptionEnum.TOKEN_EXPIRE);
			}
			else
				timeMap.put(token, System.currentTimeMillis());
		}
		return auth;
	}

	/**
	 * @param token
	 * @param userId
	 */
	@Override
	public void putAuth(String token, Long userId) {
		authMap.put(token, userId);
	}

	/**
	 * 获取token匹配的用户id
	 * @param token
	 * @return
	 */
	@Override
	public Long getUserId(String token) {
		token = null == token ? "" : token;
		return tokenMap.get(token);
	}

	/**
	 * 删除token 一个用户可能对应多个key
	 * @param userId
	 * @return
	 */
	@Override
	public void removeByUserId(Long userId) {
        tokenMap.entrySet().stream().forEach( entry -> {
            if ( userId == entry.getValue()) {
                authMap.remove(entry.getKey());
            }
        });
	}

	/**
	 * 移除有效token
	 * @param token
	 * @return
	 */
    @Override
	public Long removeByToken(String token) {
		token = null == token ? "" : token;
		authMap.remove(token);
		Long userId = tokenMap.remove(token);
		return userId;
	}

    /**
     * 检查用户权限 xx:xx:xx形式
     * @param token
     * @param perms
     * @return
     */
    @Override
    public boolean hasPerms(String token, String perms) {
        token = null == token ? "" : token;
        boolean has = false;
        List<String> permList = permsMap.get(token);
        if (null != permList) {
            has = permList.contains(token);
        }
        boolean auth = authMap.containsKey(token);
        return has || auth;
    }

    /**
     * 添加用户权限 xx:xx:xx形式
     * @param token
     * @param permsList
     */
    @Override
    public void setPerms(String token, List<String> permsList) {
        token = null == token ? "" : token;
        permsMap.put(token, permsList);
    }

    //定时清除过期token
    @Override
	public void clearTimeOut(long times) {
		Set<String> keySet = timeMap.keySet();
		for (String token : keySet) {
			Long lastTime = timeMap.getOrDefault(token, 0L);
			long interval = System.currentTimeMillis() - lastTime;
			if (interval >= times) {
				timeMap.remove(token);
				removeByToken(token);
			}
		}
	}


}
